home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / et / et-2_2.lha / et2.2 / src / CheapText.C < prev    next >
C/C++ Source or Header  |  1990-12-06  |  9KB  |  431 lines

  1. //$CheapText,CheapTextIter$
  2. #include "CheapText.h"
  3. #include "RegularExp.h"
  4. #include "Port.h"
  5. #include "Error.h"
  6.  
  7. const int cInitCap= 16;
  8.  
  9. static TextChanges changeRec;
  10.  
  11. //---- CheapText ------------------------------------------------------------
  12.  
  13. MetaImpl(CheapText, (T(next), T(size), TV(cont,next), TP(font), 0));
  14.  
  15. CheapText::CheapText(int s, FontPtr fd)
  16.     if (s < 0)
  17.     Error("CheapText::CheapText", "initial size < 0");
  18.     size= max(cInitCap, s);
  19.     cont= new byte[size];
  20.     next= 0; 
  21.     Init(next, fd);
  22. }
  23.  
  24. CheapText::CheapText(byte *t, int len, FontPtr fd)
  25. {   
  26.     int ll= len;
  27.  
  28.     if (ll == -1)
  29.     next= strlen((char*)t); 
  30.     else
  31.     next= len;
  32.  
  33.     size= max (cInitCap,(next / 5 + 1)* 6); // give some initial free space
  34.     cont= new byte[size];
  35.     BCOPY(t, cont, next);
  36.     Init(next, fd);
  37.     font= fd;
  38.     SetTabWidth(fd->Width((byte*)"        ",8));
  39. }
  40.  
  41. void CheapText::Init(int, FontPtr fd)
  42. {
  43.     font= fd;
  44.     SetTabWidth(fd->Width((byte*)"        ",8));
  45.     ink= ePatBlack;
  46. }
  47.  
  48. CheapText::~CheapText()
  49. {
  50.     SafeDelete(cont);
  51. }
  52.  
  53. void CheapText::Cut(int from,int to)
  54. {
  55.     if (!CheckRange(next, from, to))
  56.     return;
  57.  
  58.     BCOPY(&cont[to], &cont[from], next-to);
  59.  
  60.     next-= (to - from);
  61.     if (LowWaterMark()) 
  62.     Expand(size/2);
  63.     Text::Cut(from, to);
  64.     Send(cIdNone, eTextDeleted, changeRec(from, to));     
  65. }
  66.  
  67. void CheapText::Paste(TextPtr paste, int from, int to)
  68. {
  69.     CheapText *ct;
  70.     byte *buf= 0;
  71.  
  72.     if (!paste->IsKindOf(CheapText)) { // try to convert
  73.     int s= paste->Size();
  74.     buf= new byte[s+1];
  75.     paste->CopyInStr(buf, s+1, 0, s);
  76.     ct= new CheapText(buf, s);
  77.     } else
  78.     ct = (CheapText *)paste; 
  79.  
  80.     int shift= ct->next - (to - from);
  81.  
  82.     if (!CheckRange(next, from, to))
  83.     return;
  84.  
  85.     if (HighWaterMark(shift))
  86.     Expand(GrowBy(size+shift));
  87.  
  88.     if (shift < 0)
  89.     BCOPY(&cont[to], &cont[to+shift], next-to);
  90.     else if (shift > 0)
  91.     BCOPY(&cont[from], &cont[from+shift], next-from);
  92.  
  93.     //---- insert pasted text
  94.     BCOPY(ct->cont, &cont[from], ct->next);
  95.     next += shift;
  96.     if (LowWaterMark())
  97.     Expand(size/2);
  98.     if (buf) {
  99.     delete buf;
  100.     delete ct;
  101.     }
  102.     Text::Paste(paste, from, to);
  103.     Send(cIdNone, eTextReplaced, changeRec(from, to, paste->Size()));     
  104. }
  105.  
  106. void CheapText::Copy(Text *save, int from, int to)
  107. {
  108.     if (!CheckRange(next,from,to) || save == 0)
  109.     return;
  110.  
  111.     if (!save->IsKindOf(CheapText)) { // convert
  112.     int s= to - from;
  113.     byte *buf= new byte[s+1];
  114.     BCOPY(&cont[from], buf, s);
  115.     save->ReplaceWithStr(buf, s);
  116.     delete buf;
  117.     return;
  118.     }
  119.  
  120.     CheapText *ct= (CheapText *)save;    
  121.     register int nSave= to-from;
  122.  
  123.     if (ct->size < nSave) 
  124.     ct->Expand(nSave);
  125.  
  126.     BCOPY(&cont[from], ct->cont, nSave);
  127.     ct->next= nSave;
  128. }
  129.  
  130. void CheapText::CopyInStr(byte *str, int size, int from, int to)
  131. {
  132.     if (!CheckRange(next, from, to) || str == 0)
  133.     return;
  134.  
  135.     register int l= min(to, from+size-1) - from;
  136.     BCOPY(&cont[from], str, l);
  137.     str[l]= '\0';
  138. }
  139.  
  140. void CheapText::ReplaceWithStr(byte *str, int len)
  141. {
  142.     if (len == -1)
  143.     len= strlen((char*)str);
  144.     if (size < len) 
  145.     Expand(len);
  146.     BCOPY(str, cont, len);
  147.     next= len;
  148. }
  149.  
  150. void CheapText::SetFStringVL(char *fmt, va_list va)
  151. {
  152.     Empty();
  153.     char *buf= strvprintf(fmt, va);
  154.     int len= strlen(buf); 
  155.     if (size < len) 
  156.     Expand(len);
  157.     BCOPY((byte*)buf, (byte*)cont, len);
  158.     next= len;
  159.     SafeDelete(buf);
  160. }
  161.  
  162. byte *CheapText::GetTextAt(int from, int to)
  163. {
  164.     if (!CheckRange(next, from, to))
  165.     return 0;
  166.     return &cont[from];
  167. }
  168.  
  169. int CheapText::Search(RegularExp *rex, int *nMatched, int start, int range, 
  170.                          bool forward)
  171. {
  172.     int pos;
  173.  
  174.     if (forward) 
  175.     pos= rex->SearchForward((char*)cont, nMatched, start, Size(), range, 0);
  176.     else
  177.     pos= rex->SearchBackward((char*)cont, nMatched, start, Size(), range, 0); 
  178.     return pos;
  179. }
  180.  
  181. TextPtr CheapText::Save(int from, int to)
  182. {
  183.     if (!CheckRange(next, from, to))
  184.     return 0;
  185.     return new CheapText(&cont[from], to-from);
  186. }
  187.  
  188. void CheapText::Insert(byte c, int from, int to)
  189. {
  190.     int shift= to - from + 1;
  191.  
  192.     if (!CheckRange(next, from, to))
  193.     return;
  194.  
  195.     if (HighWaterMark(shift))
  196.     Expand(GrowBy(size+shift));
  197.  
  198.     if (shift < 0)
  199.     BCOPY(&cont[to], &cont[to+next], size-to);
  200.     else if (shift > 0)
  201.     BCOPY(&cont[from], &cont[from+shift], next-from);
  202.  
  203.     cont[from]= c;
  204.     next+= shift;
  205.     if (LowWaterMark())
  206.     Expand(size/2);
  207.     Text::Insert(c, from, to);
  208.     Send(cIdNone, eTextReplaced, changeRec(from, to, 1));     
  209. }
  210.  
  211. byte& CheapText::operator[](int i)
  212. {
  213.     if (!CheckRange(next, i, i))
  214.     i= size-1;
  215.     return cont[i];
  216. }
  217.  
  218. void CheapText::Empty (int)                                         
  219. {
  220.     next= 0; 
  221. }
  222.  
  223. int CheapText::Size()
  224. {
  225.     return next;
  226. }   
  227.  
  228. bool CheapText::IsEmpty() 
  229. {
  230.     return (bool) (next == 0);
  231. }
  232.  
  233. bool CheapText::IsEqual (ObjPtr text)                                         
  234. {
  235.     if (!text->IsKindOf(CheapText))
  236.     return FALSE;
  237.     CheapText *t= (CheapText *) text;   
  238.     if (next != t->next) 
  239.     return FALSE;
  240.     return (bool) (BCMP(cont, t->cont, next) == 0);
  241. }
  242.  
  243. unsigned long CheapText::Hash ()                                         
  244. {
  245.     register unsigned long hash;
  246.     register byte *p;
  247.  
  248.     for (hash= 0, p= cont; p < cont+Size(); p++)
  249.     hash= (hash << 1) ^ *p;
  250.     return hash;
  251. }
  252.  
  253. bool CheapText::IsEqualStr (byte *t)                                         
  254. {
  255.     if (next != strlen((char*)t)) 
  256.     return FALSE;
  257.     return (bool) (BCMP(cont, t, next) == 0);
  258. }
  259.  
  260. void CheapText::Expand (int newSize)                                         
  261. {
  262.     if (newSize == 0)
  263.     newSize= size * 2;
  264.  
  265.     if (newSize < Size())  // texts never shrink
  266.     return;
  267.     cont= (byte*) Realloc(cont, newSize);
  268.     next= min(newSize, next);
  269.     size= newSize;
  270. }
  271.  
  272. TextIter *CheapText::MakeIterator(int from, int to)
  273. {
  274.     return new CheapTextIter(this,from,to);
  275. }
  276.  
  277. ostream& CheapText::PrintOn(ostream& s)
  278. {
  279.     Text::PrintOn(s); 
  280.     s << font SP << ink SP;
  281.     return PrintString(s, cont, next);
  282. }
  283.  
  284. istream& CheapText::ReadFrom(istream& s)
  285. {
  286.     SafeDelete(cont);
  287.     Text::ReadFrom(s);
  288.     s >> font >> ink;
  289.     ReadString(s, &cont, &size);
  290.     next= size;
  291.     return s;
  292. }
  293.  
  294. ostream& CheapText::PrintOnAsPureText (ostream& s)
  295. {
  296.     int sz= Size();
  297.  
  298.     for (int i= 0; i < sz; i++)
  299.     s.put(CharAt(i));
  300.     return s;
  301. }
  302.  
  303. istream& CheapText::ReadFromAsPureText (istream& s, long sizeHint)
  304. {
  305.     char ch;
  306.  
  307.     if (sizeHint > 0) {
  308.     int delta= (int)(sizeHint - size); // !!!
  309.     if (delta > 0)
  310.         Expand(delta + 50);
  311.     }
  312.     next= 0; 
  313.     while (s.get(ch)) {
  314.     if (HighWaterMark(1))
  315.         Expand(GrowBy(size+1));
  316.     cont[next++] = ch;
  317.     }
  318.     if (!s.eof())
  319.     Error("ReadFromAsPureText", "something strange happened");
  320.     return s;
  321. }
  322.  
  323. int CheapText::TextWidth(int from, int to)
  324. {
  325.     if (!CheckRange(next, from ,to))
  326.     return 0;
  327.  
  328.     register int w= 0;
  329.     for (int i= from; i < to; i++) {
  330.     if (CharAt(i) == '\t') 
  331.         w+= Tabulate(w); 
  332.     else
  333.         w+= font->Width (CharAt(i));
  334.     }
  335.     return w;
  336. }
  337.  
  338. void CheapText::DrawText(int from, int to, Rectangle)
  339. {
  340.     if (!CheckRange(next, from, to))
  341.     return;
  342.  
  343.     SetDrawingState(from);
  344.     Point start= GrGetTextPos();
  345.     byte c;
  346.     for (int i= from; i < to; i++) 
  347.     if ((c= CharAt(i)) == '\t') 
  348.         GrTextAdvance(Tabulate(GrGetTextPos().x-start.x)); 
  349.     else
  350.         GrDrawChar(c);
  351. }
  352.  
  353. //----- class CheapTextIter ---------------------------------------------
  354.  
  355. CheapTextIter::CheapTextIter(Text *s, int from, int to) : TextIter(s, from, to)
  356. {
  357.     if (!s->IsKindOf(CheapText))
  358.     Error("CheapTextIter::CheapTextIter", "CheapText expected");
  359.     font= s->GetFont();
  360. }
  361.  
  362. int CheapTextIter::operator()()      // returns cEOT at end
  363. {
  364.     return (ce == upto ? cEOT : ((CheapText*)ct)->cont[ce++]);
  365. }
  366.  
  367. int CheapTextIter::operator()(int *w, LineDesc* ld)  
  368. {
  369.     CheapText *ctp = (CheapText*)ct;
  370.     int ch;
  371.  
  372.     if (ld) 
  373.     ld->FromFont(font);
  374.     unget= ce;
  375.     *w= 0;
  376.     if (ce == upto)
  377.     return cEOT;
  378.     ch= ctp->cont[ce++];
  379.     *w= font->Width(ch);
  380.     return ch;
  381. }
  382.  
  383. int CheapTextIter::Line(LineDesc* ld)  
  384. {
  385.     CheapText *ctp = (CheapText*)ct;
  386.     if (ld) 
  387.     ld->FromFont(font);
  388.  
  389.     unget= ce;
  390.     if (ce == upto) {
  391.     // special case if last line is empty
  392.     int last= ctp->cont[ce-1];
  393.     ce++;
  394.     if (last == '\n' || last == '\r') 
  395.         return upto;
  396.     }
  397.     if (ce > upto)
  398.     return cEOT;
  399.  
  400.     while (ce < upto) {
  401.     int ch= ctp->cont[ce++];
  402.     if (ch == '\n' || ch == '\r')
  403.         break;
  404.     }
  405.     return ce;
  406. }
  407.  
  408. int CheapTextIter::Token(int *w,LineDesc* ld)  
  409. {
  410.     CheapText *ctp = (CheapText*)ct;
  411.     unget= ce;
  412.     *w = 0;
  413.     if (ld) 
  414.     ld->FromFont(font);
  415.     if (ce >= upto)
  416.     return cEOT;
  417.  
  418.     register int ch= ctp->CharAt(ce);
  419.     if (Isspace(ch)) {
  420.     *w = font->Width(ch);
  421.     ce++;
  422.     return (ch);
  423.     }
  424.     while (ce < upto && !Isspace(ctp->CharAt(ce))) {
  425.     ch = ctp->CharAt(ce++);
  426.     *w += font->Width(ch);
  427.     }
  428.     return (ch);
  429. }
  430.